package phasebook.ejbclient;

import java.util.Date;
import java.util.Properties;
import java.util.Map.Entry;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import bank.RemoteBankService;
import bank.msgs.BankTransfer;

import lottery.RemoteLotteryGameService;
import lottery.msgs.LotteryBet;

import phasebook.client.RemotePhasebookService;
import phasebook.client.msgs.MessageInfo;
import phasebook.client.msgs.MovementInfo;
import phasebook.client.msgs.PhotoInfo;
import phasebook.client.msgs.UserInfo;
import phasebook.client.msgs.UserProfileInfo;

public class EJBClient {

	private static InitialContext ctx;
	static{
		try {
			Properties properties = new Properties();
			properties.load(EJBClient.class.getResourceAsStream("/jndi.properties"));
			ctx = new InitialContext();
			for(Entry<Object,Object> entry: properties.entrySet())
				ctx.addToEnvironment((String)entry.getKey(),(String)entry.getValue());
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static RemotePhasebookService getPhasebook() throws NamingException{
		return (RemotePhasebookService) ctx.lookup("phasebook/PhasebookServiceImpl/remote");
	}
	public static RemoteLotteryGameService getLottery() throws NamingException{
		return (RemoteLotteryGameService) ctx.lookup("phasebook/LotteryGameServiceImpl/remote");
	}
	
	public static RemoteBankService getBank() throws NamingException{
		return (RemoteBankService) ctx.lookup("phasebook/BankServiceImpl/remote");
	}	
	
	public static void printUserInfoArray(UserInfo[] users) throws NamingException, Exception{

		if(users == null){
			System.out.println("This list has no users.");
		}
		else{
			System.out.println("LIST START:");
			for(UserInfo user : users){
				System.out.println("UserId: " + user.getUserId() + " || Name: " + user.getName());
			}
			System.out.println("LIST END.");
		}
	}
	
	public static void printMessageInfoArray(MessageInfo[] messages) throws NamingException, Exception{

		if(messages == null){
			System.out.println("This list has no messages.");
		}
		else{
			System.out.println("LIST START:");
			for(MessageInfo message : messages){
				System.out.println("MessageId: " + message.getMessaegId() + " || Publisher: " + message.getPublisher().getName() +  " || BoardOwner: " + message.getBoardOwner().getName() + " || Text: " + message.getMessageText() + " || Timestamp: " + message.getTimestamp().toString());
			}
			System.out.println("LIST END.");
		}
	}
	
	public static void printMovementInfoArray(MovementInfo[] movements) throws NamingException, Exception{

		if(movements == null){
			System.out.println("This list has no movements.");
		}
		else{
			System.out.println("LIST START:");
			for(MovementInfo movement : movements){
				System.out.println("MessageId: " + movement.getMovementId() + " || Description: " + movement.getDescription() +  " || Amount: " + movement.getAmount() + " || Timestamp: " + movement.getTimestamp().toString());
			}
			System.out.println("LIST END.");
		}
	}	
	
	public static void testPhasebook() throws NamingException, Exception{
		// Create users 1, 2, 3
		UserProfileInfo user1 = new UserProfileInfo(100, "Nelson1", "rui_nelson1", "nelson_password1", "nelsonelson@iol.pt", 0.0,1);
		UserProfileInfo user2 = new UserProfileInfo(100, "Nelson2", "rui_nelson2", "nelson_password2", "nelson2@gmail.com", 0.0,1);
		UserProfileInfo user3 = new UserProfileInfo(100, "Nelson3", "rui_nelson3", "nelson_password3", "nelson3@gmail.com", 0.0,1);

		// Register users
		long userId1 = getPhasebook().registerUser(user1);
		long userId2 = getPhasebook().registerUser(user2);
		long userId3 = getPhasebook().registerUser(user3);
		
		System.out.println( "1 UserId: " + userId1);
		System.out.println( "2 UserId: " + userId2);
		System.out.println( "3 UserId: " + userId3);
		
		// Update User Profiles
		user1.setUserId(userId1);
		user2.setUserId(userId2);
		user3.setUserId(userId3);

		printUserInfoArray(getPhasebook().findUsers(1, "%nelson2"));		
		
		// Friendship requests (Invitations)
		
		getPhasebook().requestFriendship(userId1, userId2);
		getPhasebook().requestFriendship(userId1, userId3);
		getPhasebook().requestFriendship(userId2, userId3);
		
		// List invitations
		// User 1
		System.out.println();
		System.out.println("User 1 invitations: ");
		printUserInfoArray(getPhasebook().getFriendRequests(userId1));
		printUserInfoArray(getPhasebook().getMyFriendRequests(userId1));
		
		// User 2
		System.out.println();
		System.out.println("User 2 invitations: ");
		printUserInfoArray(getPhasebook().getFriendRequests(userId2));
		printUserInfoArray(getPhasebook().getMyFriendRequests(userId2));
		
		// User 3
		System.out.println();
		System.out.println("User 3 invitations: ");
		printUserInfoArray(getPhasebook().getFriendRequests(userId3));
		printUserInfoArray(getPhasebook().getMyFriendRequests(userId3));
		
		// Accept friendship invitation
		getPhasebook().acceptFriendshipRequest(userId2, userId1);
		
		// Deny friendship invitation
		getPhasebook().denyFriendshipRequest(userId3, userId1);
		
		// Cancel friendship invitation
		getPhasebook().cancelFriendshipRequest(userId2, userId3);
				
		// List friends
		// User 1
		System.out.println();
		System.out.println("User 1 friends: ");
		printUserInfoArray(getPhasebook().getFriends(userId1));
		
		// User 2
		System.out.println();
		System.out.println("User 2 friends: ");
		printUserInfoArray(getPhasebook().getFriends(userId2));
		
		// User 3
		System.out.println();
		System.out.println("User 3 friends: ");
		printUserInfoArray(getPhasebook().getFriends(userId3));
		
		// Cancel friendship 
		getPhasebook().cancelFriendship(userId1, userId2);
		
		// List friends
		// User 1
		System.out.println();
		System.out.println("User 1 friends: ");
		printUserInfoArray(getPhasebook().getFriends(userId1));
		
		// User 2
		System.out.println();
		System.out.println("User 2 friends: ");
		printUserInfoArray(getPhasebook().getFriends(userId2));

		// Request friendship and accept friendship
		getPhasebook().requestFriendship(userId1, userId2);
		getPhasebook().acceptFriendshipRequest(userId2, userId1);
		
		
		// Publish Messages
		MessageInfo newMessage1 = new MessageInfo(0, user1.getUserInfo(), user1.getUserInfo(), "Test text message from user 1.",	new Date(System.currentTimeMillis()), null, false);
		getPhasebook().publishMessage(newMessage1);
		
		MessageInfo newMessage2 = new MessageInfo(0, user1.getUserInfo(), user1.getUserInfo(), "Second test text message from user 1.",	new Date(System.currentTimeMillis()), null, true);
		getPhasebook().publishMessage(newMessage2);
		
		MessageInfo newMessage3 = new MessageInfo(0, user2.getUserInfo(), user2.getUserInfo(), "Test text message from user 2.",	new Date(System.currentTimeMillis()), null, false);
		getPhasebook().publishMessage(newMessage3);
		
		MessageInfo newMessage4 = new MessageInfo(0, user2.getUserInfo(), user2.getUserInfo(), "Second test text message from user 2.",	new Date(System.currentTimeMillis()), null, true);
		getPhasebook().publishMessage(newMessage4);

		MessageInfo newMessage5 = new MessageInfo(0, user2.getUserInfo(), user1.getUserInfo(), "Test text message from user 2 on the board of user 1.",	new Date(System.currentTimeMillis()), null, true);
		getPhasebook().publishMessage(newMessage5);
		
		MessageInfo newMessage6 = new MessageInfo(0, user2.getUserInfo(), user2.getUserInfo(), "Test text message from user 3 on the public board of user 2.",	new Date(System.currentTimeMillis()), null, false);
		getPhasebook().publishMessage(newMessage6);
		
		
		// List messages
		System.out.println();
		System.out.println("User 1 messages: ");
		printMessageInfoArray(getPhasebook().getMessages(userId1, userId1));
		
		System.out.println();
		System.out.println("User 2 messages: ");
		printMessageInfoArray(getPhasebook().getMessages(userId1, userId2));
		
		System.out.println();
		System.out.println("User 3 messages: ");
		printMessageInfoArray(getPhasebook().getMessages(userId3, userId1));
		
		// Update user profile
		user1.setBalance(30);
		getPhasebook().updateUser(user1);
		
		// Place bet		
		getPhasebook().placeBet(userId1, 10, 4);
		
		// Get financial movements
		System.out.println();
		System.out.println("User 1 financial movements: ");
		printMovementInfoArray(getPhasebook().getFinancialMovements(userId1));
	}
	
	public static void testBank() throws NamingException, Exception{
		
		BankTransfer bankTransfer = new BankTransfer();
		
		bankTransfer.setFromAccountId(1);
		bankTransfer.setToAccountId(2);
		bankTransfer.setSourceSystemId(1);
		bankTransfer.setTransferAmount(500.0);
		
		getBank().requestTransfer(bankTransfer);
	}
	
	public static void main(String[] args) throws Exception {
				
		testBank();
		
		System.out.println("===================");
		System.out.println("= CLIENT FINISHED =");
		System.out.println("===================");
	}
}
